package com.baijiayun.liveuibase.loading

import android.Manifest
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.Activity
import android.content.pm.PackageManager
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.baijiayun.glide.Glide
import com.baijiayun.glide.request.RequestOptions
import com.baijiayun.livecore.LiveSDK
import com.baijiayun.livecore.context.LPError
import com.baijiayun.livecore.context.LiveRoom
import com.baijiayun.livecore.listener.LPLaunchListener
import com.baijiayun.livecore.models.LPJoinCodeEnterRoomModel
import com.baijiayun.livecore.models.LPSignEnterRoomModel
import com.baijiayun.liveuibase.R
import com.baijiayun.liveuibase.utils.NetworkUtils
import com.baijiayun.liveuibase.utils.getParentViewGroup
import com.tencent.mmkv.MMKV
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.bjy_base_fragment_loading.view.*

/**
 * Created by pengwenjian on 2020/11/16
 * Describe:
 */
class LoadingWindow(private val activity: Activity, private val checkUnique: Boolean) {
    private var liveRoom: LiveRoom? = null
    private var onLoadingCompleteListener: OnLoadingCompleteListener? = null
    private var valueAnimator: ValueAnimator? = null
    private val deviceCheckResult = mutableListOf<Boolean>()
    private var loadingProgress = 0
    private var disposableOfDeviceInfo: Disposable? = null

    private val mmkv by lazy {
        MMKV.mmkvWithID("device_testing")
    }

    val view: View by lazy {
        LayoutInflater.from(activity).inflate(R.layout.bjy_base_fragment_loading, null)
    }

    /**
     * 进入直播间内部回调  最终调用外部进来的onLoadingCompleteListener 的相关接口回调到外面
     * 外部进行对应的操作
     */
    private val launchListener: LPLaunchListener = object : LPLaunchListener {
        @SuppressLint("ObjectAnimatorBinding")
        override fun onLaunchSteps(step: Int, totalStep: Int) {
            val start = loadingProgress
            val end = step * 100 / totalStep
            cancelAnimator()
            valueAnimator = ValueAnimator.ofInt(start, end)
            valueAnimator?.duration = 300
            valueAnimator?.addUpdateListener {
                loadingProgress = it.animatedValue as Int
                view.bjy_base_window_loading_progress_tv.text = activity.getString(R.string.bjy_base_window_loading_progress, loadingProgress)
            }
            valueAnimator?.start()
            onLoadingCompleteListener?.onLoadingSteps(step, totalStep)
        }

        override fun onLaunchError(error: LPError) {
            onLoadingCompleteListener?.onLoadingError(error)
        }

        override fun onLaunchSuccess(liveRoom: LiveRoom) {
            if (!TextUtils.isEmpty(mmkv.decodeString("ip"))) {
                val data = mutableMapOf<String, String>()
                data["camera_status"] = if (mmkv.decodeBool("camera_status", true)) "1" else "0"
                data["mic_status"] = if (mmkv.decodeBool("mic_status", true)) "1" else "0"
                data["speaker_status"] = if (mmkv.decodeBool("speaker_status", true)) "1" else "0"
                data["os"] = mmkv.decodeString("os")
                data["client"] = mmkv.decodeString("client")
                data["ip"] = mmkv.decodeString("ip")
                disposableOfDeviceInfo = liveRoom.uploadDeviceInfo(data)
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe ({
                            // do nothing
                        }, {
                            // do nothing
                        })
            }
            onLoadingCompleteListener?.onLoadingComplete(liveRoom)
        }
    }

    fun enterRoom(room: LiveRoom? = null, url: String?, onLoadingCompleteListener: OnLoadingCompleteListener): LiveRoom {
        this.onLoadingCompleteListener = onLoadingCompleteListener
        if (room == null) {
            liveRoom = LiveSDK.enterRoom(activity, url, launchListener)
        } else {
            liveRoom = room
            room.reconnect(launchListener)
        }
        return liveRoom!!
    }

    /**
     * 加入直播间操作，使用邀请码加入返回直播间对象
     */
    fun enterRoom(joinCodeEnterRoomModel: LPJoinCodeEnterRoomModel, onLoadingCompleteListener: OnLoadingCompleteListener): LiveRoom {
        this.onLoadingCompleteListener = onLoadingCompleteListener
        liveRoom = LiveSDK.enterRoom(activity, joinCodeEnterRoomModel, launchListener)
        return liveRoom!!
    }

    /**
     * 加入直播间操作，使用房间id roomId 加入 返回直播间对象
     */
    fun enterRoom(signEnterRoomModel: LPSignEnterRoomModel, onLoadingCompleteListener: OnLoadingCompleteListener): LiveRoom {
        this.onLoadingCompleteListener = onLoadingCompleteListener
        liveRoom = LiveSDK.enterRoom(activity, signEnterRoomModel, launchListener)
        return liveRoom!!
    }

    fun reconnect(room: LiveRoom?, onLoadingCompleteListener: OnLoadingCompleteListener) {
        this.onLoadingCompleteListener = onLoadingCompleteListener
        room?.reconnect(launchListener)
    }

    fun isLoading() = getParentViewGroup(view) != null

    fun getParentViewGroup(): ViewGroup? {
        return getParentViewGroup(view)
    }

    /**
     * 设备状态检测 如果IP 正常可以点进开始加入直播间，通过enterRoomListener.onEnterRoom()
     * 回调之后开始做加入直播间 隐藏loadingWindow
     * @param enterRoomListener
     */
    fun checkDevice(enterRoomListener: EnterRoomListener) {
        prepareWindowView()
        deviceCheckResult.clear()
        deviceCheckResult.add(!TextUtils.isEmpty(NetworkUtils.getIPAddress(activity)))
        deviceCheckResult.add(ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)
        deviceCheckResult.add(true)
        deviceCheckResult.add(ActivityCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)
        view.bjy_base_window_loading_net_check_iv.isEnabled = deviceCheckResult[0]
        view.bjy_base_window_loading_net_check_result_iv.apply {
            this.visibility = View.VISIBLE
            this.isEnabled = deviceCheckResult[0]
        }
        view.bjy_base_window_loading_camera_check_iv.isEnabled = deviceCheckResult[1]
        view.bjy_base_window_loading_camera_check_result_iv.apply {
            this.visibility = View.VISIBLE
            this.isEnabled = deviceCheckResult[1]
        }
        view.bjy_base_window_loading_speaker_check_iv.isEnabled = deviceCheckResult[2]
        view.bjy_base_window_loading_speaker_check_result_iv.apply {
            this.visibility = View.VISIBLE
            this.isEnabled = deviceCheckResult[2]
        }
        view.bjy_base_window_loading_mic_check_iv.isEnabled = deviceCheckResult[3]
        view.bjy_base_window_loading_mic_check_result_iv.apply {
            this.visibility = View.VISIBLE
            this.isEnabled = deviceCheckResult[3]
        }
        if (!deviceCheckResult[0]) {
            view.bjy_base_window_loading_device_check_result_tv.apply {
                this.text = if (deviceCheckResult[1] && deviceCheckResult[3]) {
                    activity.getString(R.string.bjy_base_window_loading_net_fail)
                } else {
                    activity.getString(R.string.bjy_base_window_loading_net_and_device_fail)
                }
                this.setTextColor(ContextCompat.getColor(activity, R.color.bjy_base_window_loading_device_check_failed_text_color))
            }
            view.bjy_base_window_loading_check_fail_button_container.visibility = View.VISIBLE
            view.bjy_base_window_loading_positive_button.apply {
                this.text = activity.getString(R.string.bjy_base_window_loading_retry)
                this.setOnClickListener {
                    prepareWindowView()
                    checkDevice(enterRoomListener)
                }
            }
            view.bjy_base_window_loading_negative_button.apply {
                this.text = activity.getString(R.string.bjy_base_window_loading_exit)
                this.setOnClickListener {
                    activity.finish()
                }
            }
        } else if (!deviceCheckResult[1] || !deviceCheckResult[3]) {
            view.bjy_base_window_loading_device_check_result_tv.apply {
                this.text = activity.getString(R.string.bjy_base_window_loading_device_fail)
                this.setTextColor(ContextCompat.getColor(activity, R.color.bjy_base_window_loading_device_check_failed_text_color))
            }
            view.bjy_base_window_loading_check_fail_button_container.visibility = View.VISIBLE
            view.bjy_base_window_loading_positive_button.apply {
                this.text = activity.getString(R.string.base_live_leave_room)
                this.setOnClickListener {
                    activity.finish()
                }
            }
            view.bjy_base_window_loading_negative_button.apply {
                this.text = activity.getString(R.string.bjy_base_window_loading_enter_room)
                this.setOnClickListener {
                    view.bjy_base_window_loading_check_fail_button_container.visibility = View.INVISIBLE
                    view.bjy_base_window_loading_progress_tv.apply {
                        this.visibility = View.VISIBLE
                        this.text = activity.getString(R.string.bjy_base_window_loading_progress, 0)
                    }
                    enterRoomListener.onEnterRoom()
                }
            }
        } else {
            view.bjy_base_window_loading_device_check_result_tv.apply {
                this.text = activity.getString(R.string.bjy_base_window_loading_device_check_path)
                this.setTextColor(ContextCompat.getColor(activity, R.color.bjy_base_window_loading_device_checking_text_color))
            }
            view.bjy_base_window_loading_progress_tv.apply {
                this.visibility = View.VISIBLE
                this.text = activity.getString(R.string.bjy_base_window_loading_progress, 0)
            }
            enterRoomListener.onEnterRoom()
        }
    }

    private fun prepareWindowView() {
        view.bjy_base_window_loading_net_check_iv.isEnabled = false
        view.bjy_base_window_loading_camera_check_iv.isEnabled = false
        view.bjy_base_window_loading_speaker_check_iv.isEnabled = false
        view.bjy_base_window_loading_mic_check_iv.isEnabled = false
        view.bjy_base_window_loading_net_check_result_iv.visibility = View.INVISIBLE
        view.bjy_base_window_loading_camera_check_result_iv.visibility = View.INVISIBLE
        view.bjy_base_window_loading_speaker_check_result_iv.visibility = View.INVISIBLE
        view.bjy_base_window_loading_mic_check_result_iv.visibility = View.INVISIBLE
        view.bjy_base_window_loading_device_check_result_tv.apply {
            this.text = activity.getString(R.string.bjy_base_window_loading_device_checking)
            this.setTextColor(ContextCompat.getColor(activity, R.color.bjy_base_window_loading_device_checking_text_color))
        }
        view.bjy_base_window_loading_check_fail_button_container.visibility = View.INVISIBLE
        view.bjy_base_window_loading_progress_tv.visibility = View.INVISIBLE
    }

    private fun cancelAnimator() {
        if (valueAnimator?.isRunning == true) {
            valueAnimator?.cancel()
            loadingProgress = 0
        }
    }

    interface EnterRoomListener {
        fun onEnterRoom()
    }
}